import java.util.*;

abstract class HasNameList<T extends HasName> extends HasName {
  
  private final Map<String,T> names2Ts = new HashMap<String,T>();

  HasNameList(String name) {
    super(name);
  }

  abstract T newInstance(String name);

  public final List<T> getValues() {
    List<T> lst = new ArrayList(names2Ts.values());
    Collections.sort(lst);
    return lst;
  }

  public final T get(String name) {
    return names2Ts.get(name);
  }

  public final void add(T t) {
    names2Ts.put(t.getName(),t);
  }

  public final T getOrCreate(String name) {
    T t = names2Ts.get(name);
    if (t == null) {
      t = newInstance(name);
      add(t);
    }
    return t;
  }

  public String toString() {
    StringBuffer s = new StringBuffer();
    toString(0,s);
    return s.toString();
  }

  public void toString(int tabs, StringBuffer s) {
    for (int i=0; i<tabs; i++) s.append(' ');
    s.append(getName());
    s.append("\n");
    for (HasName a : getValues()) {
      a.toString(tabs+1,s);
    }
  }
}